﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WPLDB.Infrastucture;
using System.Text.RegularExpressions;

namespace WPLDB.Utility.Extensions
{
    public static partial class WPLDBExtension
    {

        #region "Constant"

        #region Keyword List

        private static List<string> _listOfKeywords = new List<string> {         
                                                        "abstract",
                                                        "add",
                                                        "alias",
                                                        "as",
                                                        "ascending",
                                                        "async",
                                                        "await",
                                                        "base",
                                                        "bool",
                                                        "break",
                                                        "byte",
                                                        "case",
                                                        "catch",
                                                        "char",
                                                        "checked",
                                                        "class",
                                                        "const",
                                                        "continue",
                                                        "decimal",
                                                        "default",
                                                        "delegate",
                                                        "descending",
                                                        "do",
                                                        "double",
                                                        "dynamic",
                                                        "else",
                                                        "enum",
                                                        "event",
                                                        "explicit",
                                                        "extern",
                                                        "finally",
                                                        "fixed",
                                                        "float",
                                                        "for",
                                                        "foreach",
                                                        "from",
                                                        "get",
                                                        "global",
                                                        "goto",
                                                        "group",
                                                        "if",
                                                        "implicit",
                                                        "in",
                                                        "int",
                                                        "interface",
                                                        "internal",
                                                        "into",
                                                        "is",
                                                        "join",
                                                        "let",
                                                        "lock",
                                                        "long",
                                                        "namespace",
                                                        "new",
                                                        "null",
                                                        "object",
                                                        "operator",
                                                        "orderby",
                                                        "out",
                                                        "override",
                                                        "params",
                                                        "partial",
                                                        "private",
                                                        "protected",
                                                        "public",
                                                        "readonly",
                                                        "ref",
                                                        "remove",
                                                        "return",
                                                        "sbyte",
                                                        "sealed",
                                                        "select",
                                                        "set",
                                                        "short",
                                                        "sizeof",
                                                        "stackalloc",
                                                        "static",
                                                        "string",
                                                        "struct",
                                                        "switch",
                                                        "this",
                                                        "throw",
                                                        "try",
                                                        "typeof",
                                                        "uint",
                                                        "ulong",
                                                        "unchecked",
                                                        "unsafe",
                                                        "ushort",
                                                        "using",
                                                        "value",
                                                        "var",
                                                        "virtual",
                                                        "void",
                                                        "volatile",
                                                        "where",
                                                        "while",
                                                        "yield",
                                                        "FALSE",
                                                        "TRUE"
                                                };

        #endregion

        #endregion

        #region "Static Methods"

        /// <summary>
        /// Get string Plural
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string Plural(this string value)
        {
            if (null == value) return null;
            value = value.ToLower().RemoveSpecialChar();
            if (!value.EndsWith("s"))
                value = value.EndsWith("y") ? value.Substring(0, value.Length - 1) + "ies" : value + "s";

            return value;

        }

        /// <summary>
        /// Get string Singular
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string Singular(this string value)
        {
            if (null == value) return null;
            value = value.ToLower().RemoveSpecialChar();
            if (value.EndsWith("s"))
                value = value.EndsWith("ies") ? value.Substring(0, value.Length - 3) + "y" : value.Substring(0, value.Length - 1);


            return value;
        }

        /// <summary>
        /// Get String between two strings
        /// </summary>
        /// <param name="str"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static string Between(this string str, string start, string end)
        {
            if (null == str) return null;

            return (str.IndexOf(end, str.IndexOf(start)) - (str.IndexOf(start) + start.Length)) > 0 ?
                str.Substring(str.IndexOf(start) + start.Length, str.IndexOf(end, str.IndexOf(start)) - (str.IndexOf(start) + start.Length)) : str;

        }

        /// <summary>
        /// Replace the special character used in WPLDB string construction.
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ReplaceWPLDB(this string str)
        {
            if (null == str) return null;
            return str.Replace("-|", "{").Replace("|-", "}").Replace("[NEWLINE]", Environment.NewLine).Replace("[T]", "    ");
        }

        /// <summary>
        /// Remove _@ character
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Replace_at(this string str)
        {
            if (null == str) return null;
            return str.Replace("_@", "_");
        }

        /// <summary>
        /// Replace special character used in WPLDB
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ReplaceNewLine(this string str)
        {
            if (null == str) return null;
            return str.Replace("[NEWLINE]", Environment.NewLine).Replace("[T]", "    ");

        }

        /// <summary>
        /// Replace [CLASSNAME] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="className"></param>
        /// <returns></returns>
        public static string ReplaceClass(this string str, string className)
        {
            if (null == str) return null;
            return str.Replace("[CLASSNAME]", className);
        }

        /// <summary>
        /// Replace [CONSTRUCTORCONTENT] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static string ReplaceConstructorContent(this string str, string content)
        {
            if (null == str) return null;
            return str.Replace("[CONSTRUCTORCONTENT]", content);

        }

        /// <summary>
        ///  Replace [COMMENT+'Index'] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="content"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static string ReplaceComment(this string str, string content, int index)
        {
            if (null == str) return null;
            return str.Replace("[COMMENT" + index + "]", content);

        }

        /// <summary>
        ///  Replace [LISTOFPROPERTIES] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public static string ReplaceListOfProperties(this string str, string properties)
        {
            if (null == str) return null;
            return str.Replace("[LISTOFPROPERTIES]", properties);

        }

        /// <summary>
        ///  Replace [PROPERTYSINGULAR] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        public static string ReplacePropertySingular(this string str, string property)
        {
            if (null == str) return null;
            return str.Replace("[PROPERTYSINGULAR]", property);
        }

        /// <summary>
        ///  Replace [PROPERTY] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        public static string ReplaceProperty(this string str, string property)
        {
            if (null == str) return null;
            return str.Replace("[PROPERTY]", property);
        }

        /// <summary>
        ///  Replace [PROPERTYTYPE] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string ReplacePropertyType(this string str, string type)
        {
            if (null == str) return null;
            return str.Replace("[PROPERTYTYPE]", type);
        }

        /// <summary>
        ///  Replace [THISKEY] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string ReplacePropertyThisKey(this string str, string key)
        {
            if (null == str) return null;
            return str.Replace("[THISKEY]", key);
        }

        /// <summary>
        ///  Replace [OTHERKEY] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string ReplacePropertyOtherKey(this string str, string key)
        {
            if (null == str) return null;
            return str.Replace("[OTHERKEY]", key);
        }

        /// <summary>
        ///  Replace [FOREIGN] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string ReplaceForeignKey(this string str, string key)
        {
            if (null == str) return null;
            return str.Replace("[FOREIGN]", key);
        }

        /// <summary>
        ///  Replace [PROPERTYPLURAL] string with given string
        /// </summary>
        /// <param name="str"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        public static string ReplacePropertyPlural(this string str, string property)
        {
            if (null == str) return null;
            return str.Replace("[PROPERTYPLURAL]", property);
        }

        /// <summary>
        /// Append '@' character for C# keywords
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ReplaceCSharpKeyWords(this string str)
        {
            if (null == str) return null;
            foreach (var item in _listOfKeywords)
                if (str.Equals(item))
                    str = str.Replace(item, "@" + item);

            return str;

        }

        /// <summary>
        /// This method need to code further
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string NullableWPLDB(this string str)
        {
            return str;
        }


        /// <summary>
        /// Check IsNuallOrEmpty sting
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNullOrEmpty(this string str)
        {
            return string.IsNullOrWhiteSpace(str);

        }

        /// <summary>
        ///  Check Not IsNuallOrEmpty sting
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNotNullOrNotEmpty(this string str)
        {
            return !string.IsNullOrWhiteSpace(str);
        }

        /// <summary>
        /// Get Datasouce information from the connection string
        /// </summary>
        /// <param name="str">Connection String</param>
        /// <returns></returns>
        public static string DataSource(this string str)
        {
            if (null == str) return null;
            return (str.Contains("Data Source=") && str.Contains(";")) ? Between(str, "Data Source=", ";") : "";

        }

        /// <summary>
        /// Get the Database information from the connection string
        /// </summary>
        /// <param name="str">Connection String</param>
        /// <returns></returns>
        public static string InitialCatalog(this string str)
        {
            return null == str ? null : (str.Contains("Initial Catalog=") && str.Contains(";")) ? Between(str, "Initial Catalog=", ";") : "";
        }

        /// <summary>
        /// Remove last charactor of a string
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string RemoveLastChar(this string str)
        {
            return null == str ? null : str.Length > 0 ? str.Substring(0, str.Length - 1) : str;
        }

        /// <summary>
        /// Remove special charactor from a string
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string RemoveSpecialChar(this string str)
        {
            return null == str ? null : new Regex(@"([!@#$%^&*: ;\-()]|(?:[.](?![a-z0-9]+$)))", RegexOptions.IgnoreCase).Replace(str, "");
        }

        /// <summary>
        /// Get las project item name.
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string LastProjectItemName(this string str)
        {
            if (null != str)
            {
                var strArray = str.Split('.');
                str = strArray[strArray.Length - 1];
            }

            return str;
        }
        
        #endregion
    }
}
